package stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * steam api
 * <pre>
 * 中间操作	concat() distinct() filter() flatMap() limit() map() peek()
 * skip() sorted() parallel() sequential() unordered()
 * 结束操作	allMatch() anyMatch() collect() count() findAny() findFirst()
 * forEach() forEachOrdered() max() min() noneMatch() reduce() toArray()
 *
 * </pre>
 *
 * @author <a href="mailto:sjj@jianzhimao.com">mojo</a>
 * copyright (C), 2013-2022, 广州九尾信息科技有限公司
 * @date 2022/3/23 15:55
 */
public class StreamApi {
    public static void main(String[] args) {
        //api1();
        //收集器collector
        //collectTest();
        //collectToMap();
        //collectJoin();
        collectList();
    }

    private static void collectList() {
        List<Apple> apples = getApples();
        List<Apple> filterApple = apples.stream().filter(a -> a.getWeight() > 200).collect(Collectors.toList());
        filterApple.forEach(System.out::println);
    }

    private static void collectJoin() {
        //Collectors.join重载方法
        List<String> strings = Arrays.asList("你当像飞鸟", "飞往", "你的", "山上");
        //String collect = strings.stream().collect(Collectors.joining());
        //System.out.println(collect);
        String collect1 = strings.stream().collect(Collectors.joining("", "<<", ">>"));
        System.out.println(collect1);
    }

    private static void collectToMap() {
        /*生成map三种方式
         * 1、使用Collectors.toMap()
         * 2、使用Collectors.partitioningBy(),对元素进行二分区
         * 3.使用Collectors.groupingBy(),对元素进行group操作
         * */
        List<Apple> apples = getApples();
        Stream<Apple> stream = apples.stream();
        //toSet
        //Set<Apple> set = stream.collect(Collectors.toSet());
        //set.forEach(System.out::println);

        /*Map<String, Apple> collect = stream.collect(Collectors.toMap(a -> a.getColour()+a.isFlag(), v -> v));
        collect.forEach((k, v) -> {
            System.out.println(k);
        });*/
        //partitioning,获取重量大于200的元素，value为set
        //Map<Boolean, Set<Apple>> collect = stream.collect(Collectors.partitioningBy(a -> a.getWeight() > 200, Collectors.toCollection(HashSet::new)));
        //collect.forEach((k, v) -> {
        //    System.out.println(k);
        //    System.out.println(v);
        //});
        //分组,按照颜色分组
        //Map<String, List<Apple>> group = stream.collect(Collectors.groupingBy(Apple::getColour));
        //group.forEach((k, v) -> {
        //    System.out.println(k);
        //    System.out.println(v);
        //});
        //按照颜色分组，且只要颜色和重量
        Map<String, Set<String>> collect1 = stream.collect(Collectors.groupingBy(Apple::getColour, Collectors.mapping(a -> a.getColour() + ":" + a.getWeight(), Collectors.toSet())));
        collect1.forEach((k, v) -> {
            System.out.println(k);
            System.out.println(v);
        });
    }

    private static List<Apple> getApples() {
        List<Apple> apples = new ArrayList<>();
        apples.add(new Apple("红色", 111, true));
        apples.add(new Apple("黄色", 222, true));
        apples.add(new Apple("蓝色", 333, true));
        apples.add(new Apple("红色", 111, false));
        apples.add(new Apple("黄色", 222, false));
        apples.add(new Apple("蓝色", 333, false));
        apples.add(new Apple("粉色", 444, false));
        return apples;
    }

    private static void collectTest() {
        //collect,处理生成复杂的集合，对比reduce生成一个值
        Stream<String> s1 = Stream.of("map", "set", "list", "queue", "map");
        //Set<String>  = s1.collect(Collectors.toSet());
        TreeSet<String> set = s1.collect(TreeSet::new, Set::add, Set::addAll);
        set.forEach(System.out::println);
        //toMap
        //Map<String, String> map = s1.distinct().collect(Collectors.toMap((k -> k), v -> v + "后缀"));
        //map.forEach((k, v) -> {
        //    System.out.print(k);
        //    System.out.println(v);
        //});


    }

    private static void api1() {
        //foreach,对比Collection中的foreach
        Stream<String> s = Stream.of("one", "two", "three");
        s.filter(s1 -> s1.length() > 3)
                .forEach(System.out::println);
        //s.forEach(System.out::println);
        Stream<String> s1 = Stream.of("one", "123", "one", "three");
        //distinct
        //s1.distinct().forEach(System.out::println);
        //sorted
        //s1.sorted().forEach(e -> System.out.println(e.toUpperCase()));
        //map,flatMap
        //s1.map(e -> e.substring(0, 3)).forEach(System.out::println);

        //规约操作，reduce：sum()、max()、min()、count(),reduce生成一个值
        Optional<String> reduce = s1.reduce((s11, s22) -> s11.length() > s22.length() ? s11 : s22);
        System.out.println(reduce.get());
        Stream<Integer> s2 = Stream.of(1, 2, 3, 34, 4);
        //Optional<Integer> r1 = s2.reduce((s11, s22) -> s11 > s22 ? s11 : s22);
        //System.out.println(r1.get());
        System.out.println(">>" + s2.reduce(Integer::sum).orElseThrow(RuntimeException::new));
    }
}
